<?php
/**
 * Created by PhpStorm.
 * User: Mr.Li <lhb2002@qq.com>
 * Date: 2020/1/14
 * Time: 10:06
 */

namespace LHB\ApiEarlyWarning;

use Yansongda\Supports\Arr;

class ApiTool
{
    const PLATFORM_PREFIX = 'platform_';
    const PRODUCT_PREFIX = 'product_';
    const All_PREFIX = 'all_';

    const DELIMITER = '-';

    private static $instance ;
    private $instances = [] ;
    private $redis ;
    private $platform ;
    private $product ;

    /**
     * @var callable[]
     */
    private $subscribers = [];
    private $config = [];

    private function __construct(  \Redis $redis ,$config = [] )
    {
        $this->redis = $redis;
        $this->config = $config;
    }

    private function clone(){}

    /**
     * 获取当前容器的实例（单例）
     * @param  \Redis $redis
     * @param  array $config
     * @param  bool $newInstance
     * @return static
     */
    public static function getInstance( \Redis $redis = null ,$config = [],$newInstance = false)
    {
        if (is_null(static::$instance) || $newInstance) {
            if(!($redis instanceof \Redis)){
                throw new \RuntimeException('参数错误');
            }
            static::$instance = new static( $redis ,$config );
        }

        return static::$instance;
    }


    /**
     * @param $service
     * @return ApiEarlyWarning
     * User: Mr.Li <lhb2002@qq.com>
     * Date: 2020/1/14
     * Time: 10:34
     */
    public function makeEarlyWarning( $service )
    {
        $service_name = 'Early_' .$service;
        if( !array_key_exists( $service_name , $this->instances ) )
        {
            list($type) = explode('_' , $service );

            $this->instances[$service_name]  = $serviceObj = new ApiEarlyWarning( $this->redis , $service_name , $this->getConfig($type) );
            $serviceObj->subscribe(function ( $event , $server ,  $data ) use ( $service ){
                list($type,$service) = explode('_',$service);
                $this->notify(  $event , $type , $service,  $data );
            });
        }
        return $this->instances[$service_name];
    }

    /**
     * 获取当前平台的默认配置信息
     * @return array|mixed
     * User: Mr.Li <lhb2002@qq.com>
     * Date: 2020/1/14
     * Time: 15:50
     */
    public function getConfig( $type )
    {
        $config = Arr::get( $this->config ,$this->platform . "." .$type );
        if( is_null($config) )
        {
            $config = Arr::get(  $this->config ,"default." .$type,[] );
        }
        return $config;
    }

    /**
     * @param callable $callable
     * @return void
     */
    public function subscribe(callable $callable)
    {
        $this->subscribers[] = $callable;
    }

    /**
     * 触发回调信息
     * @param string $event
     * @param string $service
     * @param string $message
     * @return void
     */
    private function notify(  $event , $type , $service,  $data )
    {
        foreach ($this->subscribers as $s) {
            call_user_func_array($s, [ $event , $type , $service,  $data ]);
        }
    }

    /**
     * 生成统计信息
     * @param $service
     * @return Summary
     * User: Mr.Li <lhb2002@qq.com>
     * Date: 2020/1/14
     * Time: 10:42
     */
    public function makeSummary( $service )
    {
        $service_name = 'Summary_' .$service;
        if( !array_key_exists( $service_name , $this->instances ) )
        {
            $this->instances[$service_name] = new Summary( $this->redis , $service_name);
        }
        return $this->instances[$service_name];
    }

    /**
     * 设置服务
     * @param string $platform
     * @param string $product
     * @return $this
     * User: Mr.Li <lhb2002@qq.com>
     * Date: 2020/1/14
     * Time: 15:53
     */
    public function service( string $platform , string  $product )
    {
        $this->platform = $platform;
        $this->product = $product;
        return $this;
    }

    private function getPlatformKey()
    {
        return self::PLATFORM_PREFIX . $this->platform ;
    }

    private function getProductKey()
    {
        return self::PRODUCT_PREFIX . $this->platform . self::DELIMITER .$this->product ;
    }

    private function getAllKey()
    {
        return self::All_PREFIX ;
    }


    /**
     * 判断是否排除记录
     * User: Mr.Li <lhb2002@qq.com>
     * Date: 2020/1/19
     * Time: 14:16
     */
    public function isExclude()
    {
        if(array_key_exists($this->platform,$this->config['exclude'])){
            $products = $this->config['exclude'][$this->platform];
            if('*'==$products){
                return true;
            }
            elseif(is_string($products)){
                $products = explode(',',$products);
            }

            if(is_array($products) && in_array($this->product,$products)){
                return true;
            }
        }
        return false;
    }

    /**
     * 记录成功
     * User: Mr.Li <lhb2002@qq.com>
     * Date: 2020/1/9
     * Time: 14:37
     */
    public function success( string $serial_number )
    {
        if($this->isExclude())
        {
            return false;
        }
        //记录充值状态
        //$this->makeEarlyWarning($this->getPlatformKey() )->success( $serial_number );
        //$this->makeEarlyWarning($this->getProductKey() )->success( $serial_number );
        //$this->makeEarlyWarning($this->getAllKey() )->success( $serial_number );

        //记录统计数据
        $this->makeSummary($this->getPlatformKey() )->success();
        $this->makeSummary($this->getProductKey() )->success();
        $this->makeSummary($this->getAllKey() )->success();
    }

    /**
     * 记录失败
     * User: Mr.Li <lhb2002@qq.com>
     * Date: 2020/1/9
     * Time: 14:37
     */
    public function failure(  string $serial_number  )
    {
        if($this->isExclude())
        {
            return false;
        }

        //记录充值状态
        //$this->makeEarlyWarning($this->getPlatformKey() )->failure( $serial_number );
        //$this->makeEarlyWarning($this->getProductKey() )->failure( $serial_number );
        //$this->makeEarlyWarning($this->getAllKey() )->failure( $serial_number );

        //记录统计数据
        $this->makeSummary($this->getPlatformKey() )->failure();
        $this->makeSummary($this->getProductKey())->failure();
        $this->makeSummary($this->getAllKey() )->failure();
    }

    /**
     * 记录等待处理
     * @param string $message
     * User: Mr.Li <lhb2002@qq.com>
     * Date: 2020/1/10
     * Time: 9:57
     */
    public function wait ( string $serial_number  )
    {
        if($this->isExclude())
        {
            return false;
        }

        //记录充值状态
        //$this->makeEarlyWarning($this->getPlatformKey() )->wait( $serial_number );
        //$this->makeEarlyWarning($this->getProductKey() )->wait( $serial_number );
        //$this->makeEarlyWarning($this->getAllKey() )->wait( $serial_number );

        //记录统计数据
        $this->makeSummary($this->getPlatformKey() )->execute();
        $this->makeSummary($this->getProductKey())->execute();
        $this->makeSummary($this->getAllKey() )->execute();
    }

    /**
     * 记录充值异常数据
     * @param string $message
     * User: Mr.Li <lhb2002@qq.com>
     * Date: 2020/1/10
     * Time: 9:57
     */
    public function error ( string $serial_number  )
    {
        if($this->isExclude())
        {
            return false;
        }

        //记录统计数据
        $this->makeSummary($this->getPlatformKey() )->error();
        $this->makeSummary($this->getProductKey())->error();
        $this->makeSummary($this->getAllKey() )->error();
    }

    /**
     * 获取平台统计
     * @param array $fields
     * @return array|string
     * User: Mr.Li <lhb2002@qq.com>
     * Date: 2020/1/14
     * Time: 15:50
     */
    public function getPlatformSummary($fields = [] )
    {
        return $this->makeSummary($this->getPlatformKey() )->getToDaySummary();
    }

    /**
     * 获取产品统计
     * @param array $fields
     * @return array|string
     * User: Mr.Li <lhb2002@qq.com>
     * Date: 2020/1/14
     * Time: 15:50
     */
    public function getProductSummary($fields = [] )
    {
        return $this->makeSummary($this->getProductKey())->getToDaySummary();
    }

    /**
     * 获取所有的统计信息
     * @param array $fields
     * @return array|string
     * User: Mr.Li <lhb2002@qq.com>
     * Date: 2020/1/14
     * Time: 15:57
     */
    public function getAllSummary($fields = [] )
    {
        return $this->makeSummary($this->getAllKey() )->getToDaySummary();
    }

}